package com.vv.api_manage.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vv.api_manage.entity.*;
import com.vv.api_manage.mapper.ApiInterfaceItemMapper;
import com.vv.api_manage.mapper.ApiInterfaceMapper;
import com.vv.api_manage.mapper.ApiModuleMapper;
import com.vv.api_manage.service.IApiInterface;
import com.vv.api_manage.utils.UUID32;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.parser.Tag;
import org.jsoup.select.Elements;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * @Description
 * @Author xingchao
 * @Date 2020/12/30 16:04
 */
@Service
public class ApiInterfaceImpl extends ServiceImpl<ApiInterfaceMapper, ApiInterface> implements IApiInterface {
    @Autowired
    private ApiInterfaceItemMapper itemMapper;

    @Autowired
    private ApiInterfaceMapper interfaceMapper;

    @Autowired
    private ApiModuleMapper moduleMapper;

    final String KEY_DES = "api_description";
    final String KEY_REQ_PARAM = "api_request_param";
    final String KEY_RES_PARAM = "api_response_param";
    final String KEY_REQ_CASE = "api_request_case";
    final String KEY_RES_CASE = "api_response_case";

    /**
     * 接口新增
     * @param interfaceVO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> addApi(ApiInterfaceVO interfaceVO) {
        Map<String, Object> retMap = new HashMap<>();
        // 接口表
        ApiInterface apiInterface = new ApiInterface();
        BeanUtils.copyProperties(interfaceVO, apiInterface);
        apiInterface.setId(UUID32.getid());

        // 参数表
        ArrayList<ApiInterfaceItem> items = new ArrayList<>();
        String apiDescription = interfaceVO.getApiDescription();
        if (!StringUtils.isEmpty(apiDescription)) {
            items.add(createApiItem(apiInterface.getId(), KEY_DES, apiDescription));
        }
        String apiRequestCase = interfaceVO.getApiRequestCase();
        if (!StringUtils.isEmpty(apiRequestCase)) {
            items.add(createApiItem(apiInterface.getId(), KEY_REQ_CASE, apiRequestCase));
        }
        String apiRequestParam = interfaceVO.getApiRequestParam();
        if (!StringUtils.isEmpty(apiRequestParam)) {
            items.add(createApiItem(apiInterface.getId(), KEY_REQ_PARAM, apiRequestParam));
        }
        String apiResponseCase = interfaceVO.getApiResponseCase();
        if (!StringUtils.isEmpty(apiResponseCase)) {
            items.add(createApiItem(apiInterface.getId(), KEY_RES_CASE, apiResponseCase));
        }
        String apiResponseParam = interfaceVO.getApiResponseParam();
        if (!StringUtils.isEmpty(apiResponseParam)) {
            items.add(createApiItem(apiInterface.getId(), KEY_RES_PARAM, apiResponseParam));
        }

        // 模块id
        if (!StringUtils.isEmpty(interfaceVO.getModuleIdentify()) && !StringUtils.isEmpty(interfaceVO.getModulePerson())) {
            // 根据模块名称查询id 赋值
            String moduleId = this.moduleMapper.selectId(interfaceVO.getModuleIdentify(),interfaceVO.getModulePerson());
            apiInterface.setModuleId(moduleId);
        }else {
            retMap.put("retMsg_nodule","未设置moduleID，ModuleIdentify or ModulePerson is null");
        }

        apiInterface.setCreatTime(new Date());
        // 插入记录
        int insert = this.interfaceMapper.insert(apiInterface);
        if (insert < 0) {
            retMap.put("msg", "插入api_interface表失败");
            return retMap;
        }
        this.itemMapper.insertList(items);
        retMap.put("msg", "插入成功，id:"+apiInterface.getId());
        return retMap;
    }

    /**
     * 接口更新
     * @param interfaceVO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> updateApi(ApiInterfaceVO interfaceVO) {
        Map<String, Object> retMap = new HashMap<>();
        try{
            this.interfaceMapper.updateByID(interfaceVO);
        }catch (Exception e){
            retMap.put("retMsg","更新失败！ "+ interfaceVO.getId());
            return retMap;
        }
        retMap.put("retMsg","更新成功！");
        return retMap;
    }

    /**
     * html 文件导入API接口
     * @param file
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String,Object> importApi(MultipartFile file) {
        //TODO 添加一个接口截止字符串
        Map<String, Object> retMap = new HashMap<>();
        // 存放api集合
        List<ApiInterface> interfaceList = new ArrayList<>();
        List<ApiInterfaceItem> interfaceItemList = new ArrayList<>();
        try {
            InputStream inputStream = file.getInputStream();
            Document doc = Jsoup.parse(inputStream, "utf-8", "");
            Element body = doc.body();
            // 假设标题都是 h3 格式
            Elements names = body.getElementsByTag("h3");
            // 所有url地址包含在p标签内
            Elements urls = body.select("p:contains(music.51vv.com)");

            for (Element name : names) {
                ApiInterface apiInterface = new ApiInterface();
                apiInterface.setId(UUID32.getid());
                // 接口名称
                apiInterface.setApiName(name.text());

                // 获取接口作者行
                Element author = name.nextElementSibling();
                if (author.text().startsWith("接口作者")) {
                    apiInterface.setApiAuthor(author.text().substring(5));
                } else {
                    apiInterface.setApiAuthor(null);
                }

                // 接口链接
//                Element urlElement = name.nextElementSiblings().select("p:contains(music.51vv.com)").first();
//                String url = urlElement.selectFirst("a").text();
//                apiInterface.setApiAction(url);

                // 请求参数
                Element param = findParamOrRes(name, "请求参数");

                Element paramTable = param.nextElementSibling().selectFirst("table");
                if (paramTable != null) {
                    interfaceItemList = setItem(apiInterface.getId(), KEY_REQ_PARAM, paramTable, interfaceItemList);
                }

                //添加返回结果
                Element res = findParamOrRes(name, "返回结果");
                Element resTable = res.nextElementSibling().selectFirst("table");
                if (resTable != null) {
                    interfaceItemList = setItem(apiInterface.getId(), KEY_RES_PARAM, resTable, interfaceItemList);
                }

                // 获取a标签中的url
                String url = urls.get(names.indexOf(name)).selectFirst("a").text();
                apiInterface.setApiAction(url);
                apiInterface.setApiType("http");
                apiInterface.setCreatTime(new Date());
                apiInterface.setApiVersion("V1.0");
                interfaceList.add(apiInterface);
            }
            // 设置url
//            interfaceList = setUrl(urls, interfaceList);
            interfaceMapper.insertList(interfaceList);
            itemMapper.insertList(interfaceItemList);
        } catch (IOException e) {
            e.printStackTrace();
            retMap.put("retMsg","导入失败");
            return retMap;
        }
        retMap.put("retMsg","导入成功");
        return retMap;
    }


    /**
     * @return org.jsoup.nodes.Element
     * @Description 查找接口标题
     * @Author xingchao
     * @Param [element, str]
     **/
    public Element findParamOrRes(Element element, String str) {
        Tag tag = element.tag();
        if ("h4".equals(tag.toString()) && element.text().contains(str)) {
            return element;
        } else {
            element = element.nextElementSibling();
            return findParamOrRes(element, str);
        }
    }

    /**
     * 设置url
     *
     * @param urls
     * @param list
     * @return
     */
    public List<ApiInterface> setUrl(Elements urls, List<ApiInterface> list) {
        for (int i = 0; i < urls.size(); i++) {
            String uri = urls.get(i).selectFirst("a").text();
            list.get(i).setApiAction(uri);
        }
        return list;
    }

    /**
     * @return 返回传入的集合
     * @Description 设置参数、返回值、描述等
     * @Param [apiId , key, value, list：封装参数集合]
     **/
    public List<ApiInterfaceItem> setItem(String apiId, String key, Element table, List<ApiInterfaceItem> list) throws JsonProcessingException {
        Element tbody = table.select("tbody").first();
        Elements trs = tbody.select("tr");
        String data = null;

        ObjectMapper jsonMapper = new ObjectMapper();
        // list集合保存 请求参数 和 返回参数
        ArrayList<ParamItem> itemList = new ArrayList<>();
        // 创建item对象
        ApiInterfaceItem paramItem = new ApiInterfaceItem();
        paramItem.setId(UUID32.getid());
        paramItem.setApiId(apiId);
        paramItem.setKey(key);

        if (trs.size() > 0) {
            // 遍历表格行
            for (Element tr : trs) {
                // 获取每行所有列
                Elements tds = tr.select("td");
                // 一般表格都是6列，某些接口文档少一列 先拼接解决
                if (tds.size() <= 5) {
                    System.out.println();
                    for (Element td : tds) {
                        // text()方法局势返回调用标签元素中的文本内容，返回的是String类型
                        data = data + td.text() + "\t";
                    }
                    data = data + "\n";
                } else {
                    // 正常表格 ，按顺序 封装对象
                    ParamItem item = new ParamItem();
                    item.setFieldName(tds.get(0).text());
                    item.setParamName(tds.get(1).text());
                    item.setRequired(tds.get(2).text());
                    item.setParamType(tds.get(3).text());
                    item.setCaseValue(tds.get(4).text());
                    item.setDescription(tds.get(5).text());
                    itemList.add(item);
                }
            }
        }

        if (StringUtils.hasLength(data)) {
            paramItem.setValue(data);
        } else {
            paramItem.setValue(jsonMapper.writeValueAsString(itemList));
        }
        list.add(paramItem);
        return list;
    }

    /**
     * 创建 apiItem 记录
     */
    public ApiInterfaceItem createApiItem(String apiID, String key, String value) {
        ApiInterfaceItem item = new ApiInterfaceItem();
        item.setId(UUID32.getid());
        item.setApiId(apiID);
        item.setKey(key);
        item.setValue(value);
        return item;
    }
}
